package cn.imvc.app.models;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.hibernate.StaleObjectStateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.puff.cache.redis.Redis;

import cn.imvc.app.domains.GoodsState;
import cn.imvc.app.domains.PageDomain;
import cn.imvc.app.entities.Comments;
import cn.imvc.app.entities.Goods;
import cn.imvc.app.entities.GoodsAttrValue;
import cn.imvc.app.entities.GoodsClass;
import cn.imvc.app.entities.GoodsImage;
import cn.imvc.app.entities.GoodsLimitTime;
import cn.imvc.app.entities.GoodsSku;
import cn.imvc.app.entities.GoodsSpec;
import cn.imvc.app.entities.GoodsSpecValue;
import cn.imvc.app.entities.SpecClass;
import cn.imvc.app.repositories.GoodsAttrValueRepository;
import cn.imvc.app.repositories.GoodsImageRepository;
import cn.imvc.app.repositories.GoodsSkuRepository;
import cn.imvc.app.repositories.GoodsSpecRepository;
import cn.imvc.app.repositories.GoodsSpecValueRepository;
import cn.imvc.app.repositories.SpecClassRepository;
import cn.imvc.core.ICache;
import cn.imvc.util.ToolUtils;

@Service
public class GoodsSkuModelImpl implements GoodsSkuModel {
	@Autowired
	private GoodsSkuRepository goodsSkuRepository;
	@Autowired
	private GoodsSpecValueRepository goodsSpecValueRepository;
	@Autowired
	private SpecClassRepository specClassRepository;
	@Autowired
	private GoodsSpecRepository goodsSpecRepository;
	@Autowired
	private GoodsImageRepository goodsImageRepository;
	@Autowired
	private GoodsAttrValueRepository goodsAttrValueRepository;
	@Autowired
	private GoodsModel goodsModel;
	@Autowired
	private CommonModel commonModel;
	@Autowired
	private CommentsModel commentsModel;
	@Autowired
	ICache cache;
	@Autowired
	private ApplicationContext applicationContext;
	@Value("${goodsImage.inchargeSpecClassCode}")
	private String inchargeSpecClassCode;
	@Value("${memberLevelImage.url}")
	private String memberLevelImageUrl;

	@Override
	public Map<String, Object> showDetail(Integer skuId, int platform) {
		// Integer goodsSkuMaxId = cache.getSecond("MAX_ID", "goodsSku");
		//cache.remove("MAX_ID", "goodsSku");
		Integer goodsSkuMaxId = commonModel.findMaxId("goodsSku");
		if (skuId > goodsSkuMaxId) {
			return null;
		}
		PageDomain<Map<String, Object>> domain = null;
		Map<String, Object> result = null;
		String key = "skuId" + skuId + "platform" + platform;
		int minute = ToolUtils.getMinute(new Date());
	    //cache.remove("DATA", key);
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					result = getDetailInfo(skuId, platform);
					domain = new PageDomain<Map<String, Object>>();
					domain.setMapResult(result);
					cache.put("DATA", key, domain, 3600);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				result = domain.getMapResult();
				break;
			}
		}
		Goods goods = (Goods)result.get("goods");
		String[] resultTime = checkIsValidTimeGoods(goodsModel.get(goods.getId()));
		if(resultTime!=null){//为限时购商品
			result.put("goodsTimeInfo", resultTime);
		}
		return result;
	}

	private String[] checkIsValidTimeGoods(Goods goods) {
		//result[0] 状态 1:距离开始；2：距离结束；3：已结束
		//result[1] 距离开始或者结束时间
		String[] result = null;
		GoodsLimitTime goodsLimitTime = goods.getGoodsLimitTime();
		if(goodsLimitTime!=null){//属于限时购商品
			result = new String[2];
			long nowTime = System.currentTimeMillis();
			long startTime = goodsLimitTime.getStartTime().getTime();
			long endTime = goodsLimitTime.getEndTime().getTime();
			if(startTime>nowTime){//未开始
				result[0] = "1";
				result[1] = String.valueOf((startTime-nowTime));
			}else if(nowTime>endTime){//已结束
				result[0] = "3";
				result[1] = String.valueOf((startTime-endTime));
			}else{//正在进行
				result[0] = "2";
				result[1] = String.valueOf((endTime-nowTime));
			}
		}
		return result;
	}

	private Map<String, Object> getDetailInfo(Integer skuId, int platform) {
		Map<String, Object> result = new HashMap<>();
		GoodsSku goodsSku = goodsSkuRepository.findOne(skuId);
		if (goodsSku == null) {
			return null;
		}
		// sku 信息
		result.put("goodsSku", goodsSku);
		Goods goods = goodsSku.getGoods();
		// 商品基本信息
		result.put("goods", goods);
		String detailStr = goods.getDetail();
		if(detailStr!=null){
			detailStr =  detailStr.replaceAll("src=", "class=\"lazy-img\" data-original=");
			detailStr =  detailStr.replaceAll("title=", "desc=");
			detailStr =  detailStr.replaceAll("alt=", "onshow=");
		}
		result.put("goodsDeail", detailStr);
		Page<Comments> pagedComments = commentsModel.findByGoodsId(goods.getId(), null, CommentsModel.GOODS_PAGE_SIZE, "addtime_desc");
		// 评论
		result.put("pagedComments", pagedComments);
		Set<GoodsSpec> goodsSpecSet = goods.getGoodsSpec();
		if (goodsSpecSet != null && goodsSpecSet.size() > 0) {// 商品有规格分类
			Set<GoodsSpec> showSpec =  goodsSpecSet.stream().filter((spec)->spec.getSpecClass().getIsShow()==(byte)1).collect(Collectors.toSet());
			List<GoodsSpec> goodsSpecList = new ArrayList<>(showSpec);
			if(showSpec!=null&&showSpec.size()>0){
				goodsSpecList.sort((a, b) -> a.getSpecClass().getSort() - b.getSpecClass().getSort());
				// 商品规格
				result.put("goodsSpecList", goodsSpecList);
				Map<String, List<GoodsSpecValue>> goodsSpecMap = new HashMap<>();
				for (GoodsSpec goodsSpec : showSpec) {
					List<GoodsSpecValue> goodsSpecValueList = goodsSpecValueRepository.findByGoodsSpecIdOrderBySort(goodsSpec.getId());
					goodsSpecMap.put("goodsSpec" + goodsSpec.getId(), goodsSpecValueList);
				}
				// 规格属性
				result.put("goodsSpecMap", goodsSpecMap);
				// List<GoodsSku> skuCombinations =
				// goodsSkuRepository.findByGoodsId(goods.getId());
				//List<GoodsSku> skuCombinations = goodsSkuRepository.findByGoodsIdAndState(goods.getId(), (byte) 1);
				List<GoodsSku> skuCombinations = goodsSkuRepository.findByGoodsIdAndStateIn(goods.getId(), new Byte[]{(byte)GoodsState.NORMAL.getCode(),(byte)GoodsState.GIFT_STATE.getCode()});
				SimplePropertyPreFilter filter = new SimplePropertyPreFilter(GoodsSku.class, "id", "specId");
				String skuCombinationsStr = JSON.toJSONString(skuCombinations, filter);
				// sku集合的json串
				result.put("skuCombinationsStr", skuCombinationsStr);
			}
		}
		// sku图片
		result.put("goodsImageList", getGoodsImagesBySpec(goodsSku, goods));
		// 默认会员等级图片
		result.put("memberLevelImageUrl", memberLevelImageUrl);
		// goodsAttrList
		Assert.notNull(goods);
		List<GoodsAttrValue> goodsAttrList = goodsAttrValueRepository.findByGoodsId(goods.getId());
		int[] attrClassIds = goodsAttrList.stream().mapToInt(attrValue->attrValue.getAttrClass().getId()).distinct().sorted().toArray();
		result.put("attrClassIds", attrClassIds);
		if(goodsAttrList!=null&&goodsAttrList.size()>0){
			Map<String,List<GoodsAttrValue>> goodsAttrMap = goodsAttrList.stream().collect(Collectors.groupingBy(item->"attrClass"+item.getAttrClass().getId()));
			result.put("goodsAttrMap", goodsAttrMap);
		}
		//result.put("goodsAttrList", goodsAttrList);
		if (2 == platform) {// pc端
			List<GoodsClass> goodsClassList = new ArrayList<GoodsClass>();
			int time = 0;
			GoodsClass temGoodsClass = goods.getGoodsClass();
			do {
				if (temGoodsClass != null) {
					goodsClassList.add(temGoodsClass);
				}
				temGoodsClass = temGoodsClass.getParent();
				time++;
			} while (time < 3 && temGoodsClass != null);
			Collections.reverse(goodsClassList);
			// 商品分类信息
			result.put("goodsClassList", goodsClassList);
			List<Goods> hotSaleList = goodsModel.findTopListOrderBySaleNum(GoodsModel.PC_HOT_SALE_PAGE_SIZE);
			// 热销榜
			result.put("hotSaleList", hotSaleList);
			List<Goods> relationGoodsList = null;
			try {
				relationGoodsList = goodsModel.getRalationGoods(goods.getId());
				result.put("relationGoodsList", relationGoodsList);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		return result;
	}

	@Override
	public List<GoodsSku> findByGoodsId(Integer goodsId) {
		// return goodsSkuRepository.findByGoodsId(goodsId);
		return goodsSkuRepository.findByGoodsIdAndStateIn(goodsId, new Byte[]{1,3});
	}

	/**
	 * 根据规格获取商品图片
	 * 
	 * @param goodsSku
	 * @param goods
	 * @return
	 */
	private List<GoodsImage> getGoodsImagesBySpec(GoodsSku goodsSku, Goods goods) {
		List<GoodsImage> goodsImages = null;
		String[] specArr = inchargeSpecClassCode.split(",");
		for (int i = 0; i < specArr.length; i++) {
			SpecClass inchargeSpecClass = specClassRepository.findByCode(specArr[i]);
			if (inchargeSpecClass != null) {
				GoodsSpec goodsSpec = goodsSpecRepository.findBySpecClassIdAndGoodsId(inchargeSpecClass.getId(), goods.getId());
				if (goodsSpec != null) {
					String goodSkuSpecCombiantion = goodsSku.getSpecId();
					// int goodsSpecId = goodsSpec.getId();
					int goodsSpecId = goodsSpec.getSpecClass().getId();
					int goodsSpecValueId = -1;
					String[] temArr = goodSkuSpecCombiantion.split("" + goodsSpecId + ":");
					if (temArr.length == 2) {
						goodsSpecValueId = Integer.valueOf(temArr[1].split(";")[0]);
						goodsImages = goodsImageRepository.findByGoodsIdAndGoodsSpecValueId(goods.getId(), goodsSpecValueId);
						if (goodsImages != null && goodsImages.size() > 0) {
							return goodsImages;
						}
					}
				}
			}
		}
		goodsImages = new ArrayList<>(goods.getGoodsImage());
		goodsImages.sort((a, b) -> {
			if (a.getSort() == null) {
				return 1;
			}
			if (b.getSort() == null) {
				return -1;
			}
			return a.getSort() - b.getSort();
		});
		return goodsImages;
	}

	@Override
	public void retryMaintainCountsOfGoodsSku(Integer skuId, Integer clickIncrease, Integer salenumIncrease, Integer collectIncrease,
			Integer evaluationCountIncrease) {
		GoodsSku goodsSku = goodsSkuRepository.findOne(skuId);
		try {
			goodsSku.setClick((goodsSku.getClick() == null ? 0 : goodsSku.getClick()) + clickIncrease);
			goodsSku.setSalenum((goodsSku.getSalenum() == null ? 0 : goodsSku.getSalenum()) + salenumIncrease);
			goodsSku.setCollect((goodsSku.getCollect() == null ? 0 : goodsSku.getCollect()) + collectIncrease);
			// goodsSku.setEvaluationCount(goodsSku.getEvaluationCount()==null?0:goodsSku.getEvaluationCount()+evaluationCount);
			// goodsSkuRepository.saveAndFlush(goodsSku);
			goodsSkuRepository.save(goodsSku);
		} catch (StaleObjectStateException e) {
			applicationContext.getBean(GoodsSkuModel.class).retryMaintainCountsOfGoodsSku(skuId, clickIncrease, salenumIncrease, collectIncrease,
					evaluationCountIncrease);
		}
	}

	@Override
	public Integer saveIncreaseClickAndGetInventory(Integer goodsId, Integer skuId) {
		goodsModel.retrySaveGoods(goodsId, 1, 0, 0, 0);
		applicationContext.getBean(GoodsSkuModel.class).retryMaintainCountsOfGoodsSku(skuId, 1, 0, 0, 0);
		// retryMaintainCountsOfGoodsSku(skuId, 1, 0, 0, 0);
		GoodsSku goodsSku = goodsSkuRepository.findOne(skuId);
		return goodsSku.getInventory();
	}

	public List<Object[]> findMaxId() {
		return goodsSkuRepository.findAllSql("select max(id) from goods_sku");
	}

}
